#ifndef PLCELEMENT_H
#define PLCELEMENT_H

#include <QGraphicsObject>
#include <QColor>
#include <QGraphicsView>
#include <QList>
#include "connectionitem.h"

enum class PlcInstructionType
{
    NormallyOpen,
    NormallyClosed,
    Coil,
    Greater,
    GreaterEqual,
    Less,
    LessEqual,
    Equal,
    NotEqual
};

// PLC 元件基类
class PlcElement : public QGraphicsObject
{
    Q_OBJECT
public:
    explicit PlcElement(QGraphicsItem* parent = nullptr);
    ~PlcElement() override;              // 析构时清理连接

    // 添加类型定义
    enum { Type = UserType + 1 };
    // ON状态
    void setOn(bool on);
    bool isOn() const;

    void setInstructionType(PlcInstructionType type);
    PlcInstructionType instructionType() const;

    void setSize(double width, double height);
    void verticalLine(QPainter *painter, int leftMargin, int rightMargin);
    void enlarge(QPainter *painter, int leftMargin, int rightMargin, const QString& symbol);

    void addConnection(ConnectionItem *connection);
    void removeConnection(ConnectionItem *connection);
    void removeConnections();

    QList<ConnectionItem *> connections() const;

    // 获取右侧连接点（用于作为连线起点）
    QPointF startConnectionPoint() const;
    // 获取左侧连接点（用于作为连线终点）
    QPointF endConnectionPoint() const;
    // 添加连接点位置计算
    QPointF leftConnectionPoint() const;
    QPointF rightConnectionPoint() const;
    // 添加连接点检测方法
    bool isConnectionPointHit(const QPointF& pos, bool& isLeft) const;
    QRectF boundingRect() const override;

    // 共用的属性对话框内容
    void simpleDialog(PlcInstructionType t);
    // 属性对话框数据的存取
    const QString& propPrefix() const;
    int propValue() const;
    int propValue2() const;

    void setPropPrefix(const QString& p);
    void setPropValue(int v);
    void setPropValue2(int v);

    // 是否为比较元件
    bool isComparator() const;

    // 用 D 寄存器快照更新比较元件的 ON/OFF（仅比较元件生效）
    // dregs: key = D寄存器地址(整数)，value = 寄存器值（short）
    void updateCompareStateFromD(const QHash<int, quint16>& dregs);

    // 获取左右寄存器实际值（用于显示）
    quint16 leftRegisterValue() const { return m_leftRegisterValue; }
    quint16 rightRegisterValue() const { return m_rightRegisterValue; }

    void setLeftRegisterValue(quint16 value);
    void setRightRegisterValue(quint16 value);

signals:
    // 写线圈信号
    void writeCoilRequested(int address, bool value);
    // 写寄存器信号
    void writeRegisterRequested(int address, quint16 value);
    // 添加日志信号
    void logMessageRequested(const QString& message);
    // 当 M 地址被修改时发射（仅当前缀为 M 且值有变化时）
    void coilAddressChanged(int oldAddress, int newAddress);

protected:

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
    // 添加鼠标事件处理
    void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
    QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
    int type() const override;
    // 右键菜单
    void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;

protected:
    PlcInstructionType m_type;
    double m_width = 60.0;
    double m_height = 35.0;
    // ON 背景
    bool m_on = false;
    QPointF m_dragStartPos; // 记录拖动起始位置
    // 添加拖动状态标识
    enum DragState { None, Moving, Connecting };
    DragState m_dragState = None;
    bool m_dragFromRight = false; // 标记从右侧连接点拖动

private:
    QList<ConnectionItem *> m_connections;
    // 属性对话框保存的当前前缀与数值
    QString m_propPrefix = QStringLiteral("M"); // 当前类型对应的前缀：M / Y / D
    int m_propValue  = 0;                   // 数值
    int m_propValue2 = 0;               // 第二个寄存器数值
    quint16 m_leftRegisterValue = 0;    // 存储左寄存器值
    quint16 m_rightRegisterValue = 0;   // 存储右寄存器值
};

#endif // PLCELEMENT_H
